package cn.com.paycn.ken.taglib;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.DynamicAttributes;
import javax.servlet.jsp.tagext.TagSupport;

import org.apache.commons.lang3.StringUtils;

import cn.com.paycn.ken.utils.ResourceUtils;

public class PaginationTag extends TagSupport
    implements DynamicAttributes
{

    public PaginationTag()
    {
        full = "true";
        attrs = new HashMap();
    }

    private String getUrlWithParams()
    {
        Map params = pageContext.getRequest().getParameterMap();
        StringBuffer buffer = new StringBuffer();
        for(Iterator iterator = params.entrySet().iterator(); iterator.hasNext();)
        {
            java.util.Map.Entry entry = (java.util.Map.Entry)iterator.next();
            String name = (String)entry.getKey();
            if(!"page".equals(name))
            {
                String values[] = (String[])entry.getValue();
                String as[];
                int j = (as = values).length;
                for(int i = 0; i < j; i++)
                {
                    String val = as[i];
                    buffer.append((new StringBuilder(String.valueOf(name))).append("=").append(val).append("&").toString());
                }

            }
        }

        buffer.append("page=");
        return (new StringBuilder(String.valueOf(url))).append("?").append(buffer.toString()).toString();
    }

    private int getCurrentPage(int pageCount)
    {
        String page = pageContext.getRequest().getParameter("page");
        if(StringUtils.isBlank(page))
            return 1;
        int p = 1;
        try
        {
            p = Integer.parseInt(page);
            if(p < 1)
                p = 1;
            if(p > pageCount)
                p = pageCount;
        }
        catch(NumberFormatException e)
        {
            p = 1;
        }
        return p;
    }

    private int getPageCount()
    {
        int defaultRows = ResourceUtils.DEFAULT_ROWS.intValue();
        if(total.intValue() == 0)
            return 1;
        if(total.intValue() % defaultRows == 0)
            return total.intValue() / defaultRows;
        else
            return total.intValue() / defaultRows + 1;
    }

    private boolean isFull()
    {
        return "true".equals(full) || "yes".equals(full);
    }

    private boolean hasPrevPage(int currPage, int pageCount)
    {
        if(pageCount <= 1)
            return false;
        return currPage > 1 && currPage <= pageCount;
    }

    private boolean hasNextPage(int currPage, int pageCount)
    {
        if(pageCount <= 1)
            return false;
        return currPage < pageCount;
    }

    private boolean hasFirstPage(int currPage)
    {
        return currPage > 1;
    }

    private boolean hasLastPage(int currPage, int pageCount)
    {
        return currPage < pageCount;
    }

    private int getPrevPage(int currPage)
    {
        if(--currPage < 1)
            currPage = 1;
        return currPage;
    }

    private int getNextPage(int currPage, int pageCount)
    {
        if(++currPage > pageCount)
            currPage = pageCount;
        return currPage;
    }

    private ArrayList getPageNums(int currPage, int pageCount)
    {
        ArrayList nums = new ArrayList();
        if(pageCount <= 5)
        {
            for(int i = 0; i < pageCount; i++)
                nums.add(Integer.valueOf(i + 1));

        } else
        {
            int first = currPage - 3;
            int last = currPage + 2;
            if(first < 1)
            {
                first = 0;
                last = 5;
            } else
            if(last > pageCount)
            {
                first = pageCount - 5;
                last = pageCount;
            }
            for(int i = first; i < last; i++)
                nums.add(Integer.valueOf(i + 1));

        }
        return nums;
    }

    private String createPageInfoDiv(int currPage, int pageCount)
    {
        return String.format("<div class='pagination-info'>\u5F53\u524D %s \u5171 %s \u9875</div>", new Object[] {
            Integer.valueOf(currPage), Integer.valueOf(pageCount)
        });
    }

    private String createLi(String href, Object inner, String cls)
    {
        if(href == null)
            href = "javascript:;";
        if(cls == null)
            cls = "";
        return String.format("<li class='%s'><a href='%s'>%s</a></li>", new Object[] {
            cls, href, inner
        });
    }

    private String createDivAttrs()
    {
        StringBuffer buffer = new StringBuffer();
        if(!attrs.containsKey("class"))
            attrs.put("class", "pagination-div pagination");
        for(Iterator iterator = attrs.entrySet().iterator(); iterator.hasNext(); buffer.append("'"))
        {
            java.util.Map.Entry entry = (java.util.Map.Entry)iterator.next();
            buffer.append(" ");
            buffer.append((String)entry.getKey());
            buffer.append("=");
            buffer.append("'");
            buffer.append((String)entry.getValue());
        }

        return buffer.toString();
    }

    private String createTag()
    {
        String href = getUrlWithParams();
        int pageCount = getPageCount();
        int currPage = getCurrentPage(pageCount);
        int prevPage = getPrevPage(currPage);
        int nextPage = getNextPage(currPage, pageCount);
        StringBuffer buffer = new StringBuffer();
        buffer.append("<div class='row-fluid'>");
        buffer.append("<div class='span6'>");
        if(isFull())
            buffer.append(createPageInfoDiv(currPage, pageCount));
        buffer.append("</div>");
        buffer.append("<div class='span6'>");
        buffer.append("<div");
        buffer.append(createDivAttrs());
        buffer.append(">");
        buffer.append("<ul>");
        if(hasFirstPage(currPage))
            buffer.append(createLi((new StringBuilder(String.valueOf(href))).append(1).toString(), "\u9996\u9875", null));
        else
            buffer.append(createLi(null, "\u9996\u9875", "disabled"));
        if(hasPrevPage(currPage, pageCount))
            buffer.append(createLi((new StringBuilder(String.valueOf(href))).append(prevPage).toString(), "\u4E0A\u4E00\u9875", null));
        else
            buffer.append(createLi(null, "\u4E0A\u4E00\u9875", "disabled"));
        ArrayList pageNums = getPageNums(currPage, pageCount);
        for(Iterator iterator = pageNums.iterator(); iterator.hasNext();)
        {
            int i = ((Integer)iterator.next()).intValue();
            if(currPage == i)
                buffer.append(createLi((new StringBuilder(String.valueOf(href))).append(i).toString(), Integer.valueOf(i), "active"));
            else
                buffer.append(createLi((new StringBuilder(String.valueOf(href))).append(i).toString(), Integer.valueOf(i), null));
        }

        if(hasNextPage(currPage, pageCount))
            buffer.append(createLi((new StringBuilder(String.valueOf(href))).append(nextPage).toString(), "\u4E0B\u4E00\u9875", null));
        else
            buffer.append(createLi(null, "\u4E0B\u4E00\u9875", "disabled"));
        if(hasLastPage(currPage, pageCount))
            buffer.append(createLi((new StringBuilder(String.valueOf(href))).append(pageCount).toString(), "\u5C3E\u9875", null));
        else
            buffer.append(createLi(null, "\u5C3E\u9875", "disabled"));
        buffer.append("</ul>");
        buffer.append("</div>");
        buffer.append("</div>");
        buffer.append("</div>");
        return buffer.toString();
    }

    public int doStartTag()
        throws JspException
    {
        try
        {
            pageContext.getOut().write(createTag());
        }
        catch(IOException e)
        {
            throw new JspException(e);
        }
        return 0;
    }

    public void setDynamicAttribute(String uri, String localName, Object value)
        throws JspException
    {
        attrs.put(localName, String.valueOf(value));
    }

    public void setUrl(String url)
    {
        this.url = (new StringBuilder(String.valueOf(pageContext.getServletContext().getContextPath()))).append(url).toString();
    }

    public void setTotal(Integer total)
    {
        if(total == null || total.intValue() < 0)
            total = Integer.valueOf(0);
        this.total = total;
    }

    public void setFull(String full)
    {
        this.full = full;
    }

    private static final long serialVersionUID = -4465116382564687667L;
    private static final String PREV_PAGE = "\u4E0A\u4E00\u9875";
    private static final String NEXT_PAGE = "\u4E0B\u4E00\u9875";
    private static final String FIRST_PAGE = "\u9996\u9875";
    private static final String LAST_PAGE = "\u5C3E\u9875";
    private String url;
    private Integer total;
    private String full;
    private Map attrs;
}